#include "example_plugin.h"
#include <QDebug>
#include <QFile>
#include <QTextStream>
#include <QStandardPaths>
#include <QDir>
#include <QJsonDocument>

ExamplePlugin::ExamplePlugin(QObject *parent)
    : QObject(parent)
    , m_initialized(false)
{
}

ExamplePlugin::~ExamplePlugin()
{
    if (m_initialized) {
        shutdown();
    }
}

QString ExamplePlugin::pluginName() const
{
    return "Example Audit Plugin";
}

QString ExamplePlugin::pluginVersion() const
{
    return "1.0.0";
}

QString ExamplePlugin::pluginDescription() const
{
    return "Example plugin demonstrating the audit trail plugin interface";
}

QStringList ExamplePlugin::requiredPermissions() const
{
    return QStringList() << "audit.view" << "audit.export";
}

bool ExamplePlugin::initialize(const QJsonObject &config)
{
    if (m_initialized) {
        qWarning() << "Plugin already initialized";
        return false;
    }

    m_config = config;
    
    // Create plugin data directory
    QString dataDir = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + "/plugins/example";
    QDir().mkpath(dataDir);
    
    // Log initialization
    logToFile("Plugin initialized with config: " + QJsonDocument(config).toJson());
    
    m_initialized = true;
    qInfo() << "Example plugin initialized successfully";
    
    return true;
}

void ExamplePlugin::shutdown()
{
    if (!m_initialized) {
        return;
    }

    // Save any pending data
    logToFile("Plugin shutting down");
    
    // Clear event log
    m_eventLog.clear();
    m_config = QJsonObject();
    
    m_initialized = false;
    qInfo() << "Example plugin shut down";
}

bool ExamplePlugin::logEvent(const QString &userId, const QString &action, 
                            const QString &details, const QJsonObject &metadata)
{
    if (!m_initialized) {
        qWarning() << "Plugin not initialized";
        return false;
    }

    // Create event object
    QJsonObject event;
    event["timestamp"] = QDateTime::currentDateTime().toString(Qt::ISODate);
    event["userId"] = userId;
    event["action"] = action;
    event["details"] = details;
    event["metadata"] = metadata;
    event["pluginSource"] = pluginName();

    // Store in memory (in real plugin, this would go to database)
    m_eventLog.append(event);
    
    // Log to file
    QString logMessage = QString("Event logged: User=%1, Action=%2, Details=%3")
                        .arg(userId, action, details);
    logToFile(logMessage);
    
    qDebug() << "Event logged by example plugin:" << logMessage;
    return true;
}

QJsonArray ExamplePlugin::queryEvents(const QJsonObject &filter) const
{
    if (!m_initialized) {
        qWarning() << "Plugin not initialized";
        return QJsonArray();
    }

    QJsonArray results;
    
    // Filter events based on criteria
    for (const QJsonObject &event : m_eventLog) {
        if (matchesFilter(event, filter)) {
            results.append(event);
        }
    }
    
    logToFile(QString("Query executed, returned %1 events").arg(results.size()));
    return results;
}

bool ExamplePlugin::exportData(const QJsonObject &exportConfig)
{
    if (!m_initialized) {
        qWarning() << "Plugin not initialized";
        return false;
    }

    QString format = exportConfig["format"].toString("json");
    QString outputPath = exportConfig["outputPath"].toString();
    QJsonObject filter = exportConfig["filter"].toObject();
    
    if (outputPath.isEmpty()) {
        qWarning() << "No output path specified for export";
        return false;
    }

    // Query events with filter
    QJsonArray events = queryEvents(filter);
    
    // Export based on format
    QFile file(outputPath);
    if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
        qWarning() << "Failed to open export file:" << outputPath;
        return false;
    }

    QTextStream out(&file);
    
    if (format.toLower() == "json") {
        QJsonDocument doc(events);
        out << doc.toJson();
    } else if (format.toLower() == "csv") {
        // Simple CSV export
        out << "Timestamp,User ID,Action,Details\n";
        for (const QJsonValue &value : events) {
            QJsonObject event = value.toObject();
            out << event["timestamp"].toString() << ","
                << event["userId"].toString() << ","
                << event["action"].toString() << ","
                << event["details"].toString() << "\n";
        }
    } else {
        qWarning() << "Unsupported export format:" << format;
        return false;
    }
    
    file.close();
    
    QString logMessage = QString("Exported %1 events to %2 in %3 format")
                        .arg(events.size()).arg(outputPath).arg(format);
    logToFile(logMessage);
    
    return true;
}

bool ExamplePlugin::authenticateUser(const QString &username, const QString &password)
{
    // Simple demo authentication - in real plugin, this would check against actual user store
    if (username == "demo" && password == "demo123") {
        logToFile(QString("User authenticated: %1").arg(username));
        return true;
    }
    
    logToFile(QString("Authentication failed for user: %1").arg(username));
    return false;
}

bool ExamplePlugin::hasPermission(const QString &userId, const QString &permission) const
{
    // Simple demo permission check - in real plugin, this would check actual permissions
    if (userId == "admin") {
        return true; // Admin has all permissions
    }
    
    if (userId == "demo" && (permission == "audit.view" || permission == "audit.export")) {
        return true; // Demo user has basic permissions
    }
    
    return false;
}

bool ExamplePlugin::matchesFilter(const QJsonObject &event, const QJsonObject &filter) const
{
    // Check user filter
    if (filter.contains("userId")) {
        QString filterUserId = filter["userId"].toString();
        if (!filterUserId.isEmpty() && event["userId"].toString() != filterUserId) {
            return false;
        }
    }
    
    // Check action filter
    if (filter.contains("action")) {
        QString filterAction = filter["action"].toString();
        if (!filterAction.isEmpty() && event["action"].toString() != filterAction) {
            return false;
        }
    }
    
    // Check date range filter
    if (filter.contains("startDate") || filter.contains("endDate")) {
        QDateTime eventTime = QDateTime::fromString(event["timestamp"].toString(), Qt::ISODate);
        
        if (filter.contains("startDate")) {
            QDateTime startDate = QDateTime::fromString(filter["startDate"].toString(), Qt::ISODate);
            if (eventTime < startDate) {
                return false;
            }
        }
        
        if (filter.contains("endDate")) {
            QDateTime endDate = QDateTime::fromString(filter["endDate"].toString(), Qt::ISODate);
            if (eventTime > endDate) {
                return false;
            }
        }
    }
    
    return true;
}

void ExamplePlugin::logToFile(const QString &message)
{
    QString logDir = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + "/plugins/example";
    QString logFile = logDir + "/plugin.log";
    
    QFile file(logFile);
    if (file.open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Text)) {
        QTextStream out(&file);
        out << QDateTime::currentDateTime().toString(Qt::ISODate) 
            << " - " << message << "\n";
    }
}